<?php
/**
 * Created by PhpStorm.
 * User: zd
 * Date: 2018/11/24
 * Time: 11:39
 */
namespace app\server\controller;

use app\api\model\ThirdApp;
use app\api\model\WorkUser;
use app\api\service\BehaviorMessage;
use app\api\service\Card;
use app\api\service\DeliveryMessage;
use app\api\service\Token;
use GatewayWorker\Lib\Gateway;
use think\Cache;
use think\Config;
use think\Log;

class Events
{
    /**
     * 有消息时
     * @param $client_id
     * @param $message
     * @return bool|string|void
     * @throws \Exception
     */
    public static function onMessage($client_id, $message)
    {
        $result = '';
        // debug
        //echo "client:{$_SERVER['REMOTE_ADDR']}:{$_SERVER['REMOTE_PORT']} gateway:{$_SERVER['GATEWAY_ADDR']}:{$_SERVER['GATEWAY_PORT']}  client_id:$client_id session:".json_encode($_SESSION)." onMessage:".$message."\n";
        // 客户端传递的是json数据
        $message_data = json_decode($message, true);
        if(!$message_data)
        {
            return '';
        }
        // 根据类型执行不同的业务
        switch($message_data['type'])
        {
            // 客户登录
            case 'login':
                $arr = self::login($client_id, $message_data, $arr=[]);
                return Gateway::sendToCurrentClient(json_encode($arr));
            // 客户端回应服务端的心跳
            case 'pong':
                    $new_message['type']='ping';
                return Gateway::sendToCurrentClient(json_encode($new_message));
            // 客户端发言 message: {type:say, to_client_id:xx, content:xx}
            case 'say':
                    //准备入库聊天记录
                    $data = (new Events())->prepareMessageData($client_id, $message_data, $data=[]);
                    $insertData = ['data'=>$data,'message_data'=>$message_data];//异步数据准备
                    new DeliveryTask('insertMessage',$insertData);//异步入库
                    //判断用户是否在线
                    if (Gateway::isUidOnline($message_data['to_client'])){
                        list($to_client_id, $new_message) = self::sendMessage($client_id, $message_data);
                        $result =  Gateway::sendToClient($to_client_id, json_encode($new_message));
                    }else{
                        new DeliveryTask('sendMessage',$insertData);//异步消息发送
                    }
                    //返回消息发送状态
                    $message_data['type'] = !$result ? 'fail':'sucess';
                    return  Gateway::sendToCurrentClient(json_encode($message_data));
                }
    }
    /**
     * 当客户端断开连接时
     * @param integer $client_id 客户端id
     */
    public static function onClose($client_id)
    {
        // 从房间的客户端列表中删除
        Gateway::closeClient($client_id,"链接已断开");
    }

    /**
     * 传递消息
     * @param $client_id
     * @param $message_data
     * @return array
     */
    private static function sendMessage($client_id, $message_data): array
    {
        $data = Gateway::getClientIdByUid($message_data['to_client']);
        foreach ($data as $value) {
            if (Gateway::isOnline($value)) {
                $to_client_id = $value;
            }
        }
        $new_message = array(
            'type' => 'say',
            'from_client_id' => $client_id,
            'to_client_id' => $to_client_id,
            'uid' => Gateway::getUidByClientId($client_id),
            'head_img' => $message_data['head_img'],
            'user_name' => $message_data['user_name'],
            'message_type' => $message_data['message_type'],
            'content' => nl2br(htmlspecialchars($message_data['content'])),
            'time' => date('Y-m-d H:i:s'),
        );
        return array($to_client_id, $new_message);
    }

    /**
     * 长连接
     * @param $client_id
     * @param $message_data
     * @param $arr
     * @return mixed
     */
    private static function login($client_id, $message_data, $arr)
    {
        $token = $message_data['token'];
        try{
            $data = Token::getCurrentToken($token);
            $uid = $data['uid'];
            Gateway::bindUid($client_id, $uid);
            $arr['code'] = 200;
            $arr['msg'] = 'link success';
        }catch (\Exception $exception){
            $arr['code'] = 999;
            $arr['msg'] = 'link fail';
            Log::record($arr);
            //insertLog(APP_PATH.'vendor/workerman/error.log',time(),$arr);//日志记录
        }
        $arr['type'] = 'login';
        $arr['client_id'] = $client_id;
        return $arr;
    }
    /**
     * 准备入库的聊天记录
     * @param $client_id
     * @param $message_data
     * @param $data
     * @return array
     */
    private function prepareMessageData($client_id, $message_data, $data)
    {
        if ($message_data['user_type'] == 1) {
            $data['from_uid'] = Gateway::getUidByClientId($client_id);
        } elseif ($message_data['user_type'] == 2) {
            $data['from_wu_id'] = Gateway::getUidByClientId($client_id);
        }
        $data['id'] = Gateway::getUidByClientId($client_id);
        return $data;
    }
}